package net.socket;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

public class RequestProcessor implements Runnable
{
	private static List<Socket> pool = new LinkedList<Socket>();
	private File documentRootDirectory;
	private String indexFileName = "index.html";
	public RequestProcessor(File documentRoot,String indexFileName) throws IllegalAccessException
	{
		if(documentRoot.isFile())
		{
			throw new IllegalAccessException("must be a directory.");
		}
		this.documentRootDirectory = documentRoot;
		try
		{
			this.documentRootDirectory = documentRootDirectory.getCanonicalFile();
		}
		catch (Exception e)
		{
		}
		if(indexFileName!=null)
		{
			this.indexFileName = indexFileName;
		}
	}
	public static void processRequest(Socket request)
	{
		synchronized (pool)
		{
			pool.add(pool.size(),request);
			pool.notifyAll();
		}
	}
	@Override
	public void run()
	{
		String root = documentRootDirectory.getPath();
		while(true)
		{
			Socket connection;
			synchronized (pool)
			{
				while(pool.isEmpty())
				{
					try
					{
						pool.wait();
					}
					catch (Exception e)
					{
					}
				}
				connection = pool.remove(0);
			}
			try
			{
				String filename;
				String contentType;
				OutputStream raw = new BufferedOutputStream(connection.getOutputStream());
				Writer out = new OutputStreamWriter(raw);
				Reader in = new InputStreamReader(connection.getInputStream(),"ASCII");
				StringBuffer requestLine =  new StringBuffer();
				int c;
				while(true)
				{
					c = in.read();
					if(c=='\r'||c=='\n')
					{
						break;
					}
					requestLine.append(c);
				}
				String get = requestLine.toString();
				System.out.println(get);
				StringTokenizer st = new StringTokenizer(get);
				String method = st.nextToken();
				String version = "";
				if(method.equals("GET"))
				{
					filename = st.nextToken();
					if(filename.endsWith("/"))
					{
						filename +=indexFileName;
					}
					contentType = guessContentTypeFromName(filename);
					if(st.hasMoreElements())
					{
						version = st.nextToken();
					}
					File theFile = new File(documentRootDirectory,filename.substring(1,filename.length()));
					if(theFile.canRead()&&theFile.getCanonicalPath().startsWith(root))
					{
						DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(theFile)));
						byte[] theData = new byte[(int) theFile.length()];
						fis.readFully(theData);
						fis.close();
						if(version.startsWith("HTTP"))
						{
							out.write("HTTP/1.0 200 OK\r\n");
							Date now = new Date();
							out.write("Date: "+now+"\r\n");
							out.write("Server: JHTTP/1.0\r\n");
							out.write("Content-length:"+theData.length+"\r\n");
							out.write("Content-type: "+contentType+"\r\n\r\n");
							out.flush();
						}
						raw.write(theData);
						raw.flush();
					}
					else
					{
						if(version.startsWith("HTTP "))
						{
							out.write("HTTP/1.0 404 File Not Found\r\n");
							Date now = new Date();
							out.write("Date: "+now+"\r\n");
							out.write("Server: JHTTP/1.0\r\n");
							out.write("Content-type: text/html\r\n\r\n");
						}
					}
				}
				
			}
			catch (Exception e)
			{
			}
			finally
			{
				try
				{
					connection.close();
				}
				catch (Exception e2)
				{
				}
			}
		}
	}
	public static String guessContentTypeFromName(String name)
	{
		if(name.endsWith(".html")||name.endsWith(".htm"))
		{
			return "text/html";
		}
		else if(name.endsWith(".txt")||name.endsWith(".java"))
		{
			return "text/plain";
		}
		else if(name.endsWith(".gif"))
		{
			return "image/gif";
		}
		else if(name.endsWith(".class"))
		{
			return "application/octet-stream";
		}
		else if(name.endsWith(".jpg")||name.endsWith(".jepg"))
		{
			return "image/jepg";
		}
		else
		{
			return "text/plain";
		}
	}
	
}
